package com.zhdl.common.ytools;

import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.HexUtil;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;

/**
 * 进制转换工具
 */
@Slf4j
public class BaseConversionTools extends HexUtil {

    /**
     * byte数组转十六进制字符串
     *
     * @param data byte数组
     * @return 十六进制字符串
     */
    public static String byteArrayToHex(byte[] data) {
        return encodeHexStr(data, true);
    }

    /**
     * 十六进制字符串转byte数组
     *
     * @param hexStr 十六进制字符串
     * @return byte数组
     */
    public static byte[] hexToByteArray(String hexStr) {
        return decodeHex((CharSequence) hexStr);
    }

    /**
     * 字符串转十六进制字符串
     *
     * @param data 字符串
     * @return 十六进制字符串
     */
    public static String strToHexStr(String data) {
        return encodeHexStr(data, CharsetUtil.CHARSET_UTF_8);
    }

    /**
     * 十六进制字符串转字符串
     *
     * @param hexStr 十六进制字符串
     * @return 字符串
     */
    public static String hexStrToStr(String hexStr) {
        return decodeHexStr(hexStr, CharsetUtil.CHARSET_UTF_8);
    }

    /* 基本进制转换 For Example -> { 二进制 十进制 十六进制 } */

    /**
     * 十进制转十六进制
     */
    public static String decToHex(int value) {
        return Integer.toHexString(value);
    }

    /**
     * 十六进制转十进制
     */
    public static int hexToDec(String value) {
        return Integer.parseInt(value, 16);
    }

    /**
     * long转十六进制
     */
    public static String longToHex(long value) {
        return Long.toHexString(value);
    }

    /**
     * 十六进制转long
     */
    public static long hexToLong(String value) {
        return Long.parseLong(value, 16);
    }

    /* 进阶进制转换 For Example -> { 二进制 十进制 十六进制 } */

    /**
     * Int转十六进制 两个寄存器
     *
     * @param value 10进制值
     * @return 八个字符的十六进制
     */
    public static String intToIntHex(int value) {
        StringBuilder stringBuilder = new StringBuilder(8);
        writeHex(stringBuilder, (long) value & 4294967295L, 8, "");
        return stringBuilder.toString();
    }

    /**
     * Int转十六进制 一个寄存器
     *
     * @param value 10进制值
     * @return 四个字符的十六进制
     */
    public static String intToShortHex(int value) {
        StringBuilder sb = new StringBuilder(4);
        writeHex(sb, (long) value & 65535L, 4, "");
        return sb.toString();
    }


    public static float hexToFloat(String hex) {
        // int i = Integer.parseInt(hex, 16);
        BigInteger bigInteger = new BigInteger(hex, 16);
        return Float.intBitsToFloat(bigInteger.intValue());
    }


    /**
     * Int转十六进制 一个字节
     *
     * @param value 10进制值
     * @return 四个字符的十六进制
     */
    public static String intToByteHex(int value) {
        StringBuilder sb = new StringBuilder(2);
        writeHex(sb, (long) value & 255L, 2, "");
        return sb.toString();
    }

    /**
     * Int转十六进制 四个寄存器
     *
     * @param value 10进制值
     * @return 四个字符的十六进制
     */
    public static String longToByteHex(long value) {
        StringBuilder sb = new StringBuilder(16);
        writeHex(sb, value, 16, "");
        return sb.toString();
    }

    public static int hexToSignInt(String hex) {
        if (hex.length() < 8) {
            return -999;
        } else {
            return new BigInteger(hex, 16).intValue();
        }
    }

    public static int hexToSignShort(String hex) {
        if (hex.length() < 4) {
            return -999;
        } else {
            return Integer.valueOf(hex, 16).intValue();
        }
    }

    public static int hexToSignByte(String hex) {
        if (hex.length() < 2) {
            return -999;
        } else {
            return Integer.valueOf(hex, 16).byteValue();
        }
    }

    /**
     * 修改的值
     *
     * @param stringBuilder 十六进制的存放
     * @param value         Int值
     * @param nDigits       字符串的数量
     * @param prefix        前缀
     */
    private static void writeHex(StringBuilder stringBuilder, long value, int nDigits, String prefix) {
        stringBuilder.append(prefix);
        char[] buf = new char[nDigits];
        long acc = value;
        for (int i = nDigits - 1; i >= 0; --i) {
            int digit = (int) (acc & 15L);
            buf[i] = (char) (digit < 10 ? 48 + digit : 65 + digit - 10);
            acc >>>= 4;
        }
        stringBuilder.append(buf);
    }

    public static String HeightLowRollBack(String hex) {
        if (hex.length() == 8) {
            return hex.substring(4, 8) + hex.substring(0, 4);
        } else {
            return hex;
        }
    }


    /* ASCII && HexBase Conversion */

    /**
     * 将ASCII字符转换为十六进制字符串
     *
     * @param asciiChar ASCII字符
     * @return 对应的十六进制字符串
     */
    public static String asciiCharToHex(char asciiChar) {
        // 获取字符的ASCII值（即Unicode值），然后转换为十六进制字符串
        String hex = Integer.toHexString(asciiChar);
        // 如果只有一位，前面补0
        if (hex.length() == 1) {
            hex = "0" + hex;
        }
        return hex;
    }

    /**
     * 将GBK编码的字符串转换为十六进制字符串
     *
     * @param gbkString GBK编码的字符串
     * @return 对应的十六进制字符串
     * @throws UnsupportedEncodingException 如果GBK编码不被支持（这通常不会发生）
     */
    public static String gbkStringToHex(String gbkString) throws UnsupportedEncodingException {
        // 获取GBK编码的字节数组
        byte[] bytes = gbkString.getBytes("GBK");

        // 将字节数组转换为十六进制字符串
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }

        return hexString.toString();
    }

    /**
     * 将UTF-8 编码的字符串转换为十六进制字符串
     *
     * @param utf8String UTF-8 编码的字符串
     * @return 对应的十六进制字符串
     */
    public static String utf8StringToHex(String utf8String) {
        // 获取UTF-8编码的字节数组
        byte[] bytes = utf8String.getBytes(StandardCharsets.UTF_8);

        // 将字节数组转换为十六进制字符串
        StringBuilder hexString = new StringBuilder();
        for (byte b : bytes) {
            // 将字节转换为无符号整数（0-255），然后转换为两位的十六进制字符串
            String hex = Integer.toHexString(b & 0xff);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }

        return hexString.toString();
    }

    /**
     * 将十六进制字符串转换为ASCII字符串
     *
     * @param hexString 十六进制字符串（可包含空格、换行符等分隔符）
     * @return 转换后的ASCII字符串
     * @throws IllegalArgumentException 如果输入的字符串包含非十六进制字符
     */
    public static String hexStringToAscii(String hexString) {
        // 移除所有非十六进制字符（空格、换行符等）
        hexString = hexString.replaceAll("[^0-9A-Fa-f]", "");

        // 如果字符串长度为奇数，则无法转换为有效的字节数组，抛出异常
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("无效的十六进制字符串，长度必须为偶数");
        }

        // 将字符串转换为字节数组
        byte[] bytes = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            // 每两个字符对应一个字节
            String byteValue = hexString.substring(i, i + 2);
            int byteAsInt = Integer.parseInt(byteValue, 16);
            bytes[i / 2] = (byte) byteAsInt;
        }

        // 将字节数组转换为ASCII字符串
        return new String(bytes);
    }

    /**
     * 将GBK编码的十六进制字符串转换为字符串
     *
     * @param hexString GBK编码的十六进制字符串（每两个字符表示一个字节）
     * @return 转换后的字符串（包括中文字符）
     * @throws IllegalArgumentException     如果输入的字符串长度不是偶数
     * @throws UnsupportedEncodingException 如果GBK编码不被支持（这通常不会发生，因为GBK是Java支持的编码之一）
     */
    public static String hexStringToGbk(String hexString) throws UnsupportedEncodingException {
        // 移除所有非十六进制字符（空格、换行符等）
        hexString = hexString.replaceAll("[^0-9A-Fa-f]", "");

        // 如果字符串长度为奇数，则无法转换为有效的字节数组，抛出异常
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("无效的十六进制字符串，长度必须为偶数");
        }

        // 将十六进制字符串转换为字节数组
        byte[] bytes = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            // 每两个字符对应一个字节
            String byteValue = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(byteValue, 16);
        }

        // 将字节数组解码为GBK字符串
        return new String(bytes, "GBK");
    }

    /**
     * 将UTF-8 编码的十六进制字符串转换为字符串
     *
     * @param hexString UTF-8 编码的十六进制字符串（每两个字符表示一个字节）
     * @return 转换后的字符串（包括中文字符）
     * @throws IllegalArgumentException 如果输入的字符串长度不是偶数
     */
    public static String hexStringToUtf8(String hexString) {
        // 移除所有非十六进制字符（空格、换行符等）
        hexString = hexString.replaceAll("[^0-9A-Fa-f]", "");

        // 如果字符串长度为奇数，则无法转换为有效的字节数组，抛出异常
        if (hexString.length() % 2 != 0) {
            throw new IllegalArgumentException("无效的十六进制字符串，长度必须为偶数");
        }

        // 将十六进制字符串转换为字节数组
        byte[] bytes = new byte[hexString.length() / 2];
        for (int i = 0; i < hexString.length(); i += 2) {
            // 每两个字符对应一个字节
            String byteValue = hexString.substring(i, i + 2);
            bytes[i / 2] = (byte) Integer.parseInt(byteValue, 16);
        }

        // 将字节数组解码为UTF-8字符串
        return new String(bytes, StandardCharsets.UTF_8);
    }
    public static String floatToHex(float num) {
        int i = Float.floatToIntBits(num);
        return Integer.toHexString(i);
    }
    public static String floatTo8hex(float f){
        String hexSpeed = floatToHex(f);
        StringBuilder runHex = new StringBuilder(hexSpeed);
        int len = runHex.length();
        if (runHex.length() < 8) {
            for (int i = 0; i < 8 - len; i++) {
                runHex.insert(0, "0");
            }
        }
        return runHex.toString();
    }

    public static String floatTo8hexHL(float f){
        String hexSpeed = floatToHex(f);
        StringBuilder runHex = new StringBuilder(hexSpeed);
        int len = runHex.length();
        if (runHex.length() < 8) {
            for (int i = 0; i < 8 - len; i++) {
                runHex.insert(0, "0");
            }
        }
        return coverHexHL(runHex.toString());
    }
    public static  String coverHexHL(String hex){
        if (hex.length() == 8){
         return hex.substring(4,8)+hex.substring(0,4);
        }else{
            return hex;
        }
    }
    public static String asciiToHex(String asciiStr) {
        StringBuilder hexStr = new StringBuilder();
        for (int i = 0; i < asciiStr.length(); i++) {
            char c = asciiStr.charAt(i);
            String charHex = asciiCharToHex(c);
            hexStr.append(charHex);
        }
        return hexStr.toString();
    }
}
